// 简化版Redux实现 - 用于展示Redux核心原理

// Action类型定义
export interface Action<T = any> {
  type: string;
  payload?: T;
}

// Reducer类型定义
export type Reducer<S = any, A extends Action = Action> = (
  state: S | undefined,
  action: A
) => S;

// Dispatch类型定义
export type Dispatch<A extends Action = Action> = (action: A) => A;

// Middleware类型定义
export interface MiddlewareAPI<D extends Dispatch = Dispatch, S = any> {
  dispatch: D;
  getState: () => S;
}

export type Middleware<D extends Dispatch = Dispatch, S = any> = (
  api: MiddlewareAPI<D, S>
) => (next: D) => D;

// Store类型定义
export interface Store<S = any, A extends Action = Action> {
  dispatch: Dispatch<A>;
  getState: () => S;
  subscribe: (listener: () => void) => () => void;
  replaceReducer: (nextReducer: Reducer<S, A>) => void;
}

// compose函数 - 组合函数，用于中间件链的构建
function compose(...funcs: Function[]) {
  if (funcs.length === 0) {
    return (arg: any) => arg;
  }

  if (funcs.length === 1) {
    return funcs[0];
  }

  return funcs.reduce((a, b) => (...args: any[]) => a(b(...args)));
}

// createStore函数 - 创建Redux Store
export function createStore<S, A extends Action>(
  reducer: Reducer<S, A>,
  preloadedState?: S,
  enhancer?: any
): Store<S, A> {
  // 如果只提供了两个参数且第二个参数是函数，则将其视为enhancer
  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState;
    preloadedState = undefined;
  }

  // 如果提供了enhancer，则使用enhancer来增强createStore
  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function');
    }

    return enhancer(createStore)(reducer, preloadedState as S);
  }

  if (typeof reducer !== 'function') {
    throw new Error('Expected the reducer to be a function');
  }

  let currentReducer = reducer;
  let currentState = preloadedState as S;
  let currentListeners: (() => void)[] = [];
  let nextListeners = currentListeners;
  let isDispatching = false;

  // 确保nextListeners是currentListeners的副本
  function ensureCanMutateNextListeners() {
    if (nextListeners === currentListeners) {
      nextListeners = currentListeners.slice();
    }
  }

  // 获取当前状态
  function getState(): S {
    if (isDispatching) {
      throw new Error('You may not call getState() while the reducer is executing.');
    }

    return currentState;
  }

  // 订阅状态变化
  function subscribe(listener: () => void): () => void {
    if (typeof listener !== 'function') {
      throw new Error('Expected the listener to be a function');
    }

    if (isDispatching) {
      throw new Error('You may not call subscribe() while the reducer is executing.');
    }

    let isSubscribed = true;

    ensureCanMutateNextListeners();
    nextListeners.push(listener);

    // 返回取消订阅的函数
    return function unsubscribe() {
      if (!isSubscribed) {
        return;
      }

      if (isDispatching) {
        throw new Error('You may not unsubscribe from a store listener while the reducer is executing.');
      }

      isSubscribed = false;

      ensureCanMutateNextListeners();
      const index = nextListeners.indexOf(listener);
      nextListeners.splice(index, 1);
      currentListeners = [];
    };
  }

  // 分发action
  function dispatch(action: A): A {
    if (!action || typeof action.type === 'undefined') {
      throw new Error('Actions must have a type property.');
    }

    if (isDispatching) {
      throw new Error('Reducers may not dispatch actions.');
    }

    try {
      isDispatching = true;
      // 调用reducer计算新的状态
      currentState = currentReducer(currentState, action);
    } finally {
      isDispatching = false;
    }

    // 通知所有订阅者
    const listeners = (currentListeners = nextListeners);
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i];
      listener();
    }

    return action;
  }

  // 替换reducer
  function replaceReducer(nextReducer: Reducer<S, A>) {
    if (typeof nextReducer !== 'function') {
      throw new Error('Expected the nextReducer to be a function');
    }

    currentReducer = nextReducer;
    dispatch({ type: '@@redux/INIT' } as A);
  }

  // 初始化状态
  dispatch({ type: '@@redux/INIT' } as A);

  return {
    dispatch,
    getState,
    subscribe,
    replaceReducer
  };
}

// applyMiddleware函数 - 应用中间件
export function applyMiddleware<S = any>(
  ...middlewares: Middleware<Dispatch<Action>, S>[]
) {
  return (createStore: Function) => (reducer: Reducer<S, Action>, preloadedState?: S) => {
    const store = createStore(reducer, preloadedState);
    let dispatch: Dispatch<Action> = function() {
      throw new Error(
        'Dispatching while constructing your middleware is not allowed. '
      );
    } as Dispatch<Action>;

    const middlewareAPI: MiddlewareAPI<Dispatch<Action>, S> = {
      getState: store.getState,
      dispatch: (action: Action) => dispatch(action)
    };

    // 为每个中间件传入middlewareAPI
    const chain = middlewares.map(middleware => middleware(middlewareAPI));
    // 组合中间件链并增强dispatch
    dispatch = compose(...chain)(store.dispatch);

    return {
      ...store,
      dispatch
    };
  };
}